package logger

import (
	"fmt"
	"os"
	"strings"
	"sync"

	logger2 "sources.bindo.co/backend/service-common/helpers/logger"
)

func init() {
	// init setting
}

type (
	Log struct {
		MsgPrefix       string
		DepthInfo       []Info
		Depth           int
		FuncName        string
		StartMsgPrefix  string
		EndMsgPrefix    string
		IndentMsg       string
		PrefixIndentMsg string
		IgnoreFuncs     map[string]bool
		Lock            sync.RWMutex
	}
)

type Info struct {
	FuncName string
	Msg      string
}

var Logger = &Log{
	DepthInfo:       make([]Info, 0, 5),
	Depth:           0,
	MsgPrefix:       "**    ",
	StartMsgPrefix:  "** >  ",
	EndMsgPrefix:    "** <  ",
	IndentMsg:       "  .  ",
	PrefixIndentMsg: "     ",
	// IgnoreList:      make(map[string]bool),
	IgnoreFuncs: map[string]bool{},
	Lock:        sync.RWMutex{},
}

func init() {
	ignoreFuncs := os.Getenv("ignore_funcs")
	funcs := strings.Split(ignoreFuncs, ",")
	for _, funcname := range funcs {
		Logger.IgnoreFuncs[funcname] = true
		println("[ logger.warring ], log will ignore func:[", funcname, "]")
	}
}

func (logger *Log) MyPrintf(format string, args ...interface{}) {
	// println("funaname:", logger.FuncName, logger.DepthInfo, logger.Depth)
	if logger.IgnoreFuncs[logger.FuncName] {
		// println(logger.FuncName, "is in ignore list")
		return
	}
	// fmt.Printf(format, args...)
	// logger2.Infof(format, args...)
	// logger2.GetLogger().WithField("info").Infof(format, args...)
	logger2.GetLogger().WithField("mode", "mylog").Errorf(format, args...)
}

func (logger *Log) Start(name, msg string) {
	logger.Lock.Lock()
	defer logger.Lock.Unlock()
	logger.FuncName = name
	logger.Depth += 1
	logger.DepthInfo = append(logger.DepthInfo, Info{
		FuncName: name,
		Msg:      msg,
	})
	logger.MyPrintf("\n\n%s -> %v func %s: %s\n\n", logger.StartMsgPrefix, logger.Depth, name, msg)
	logger.MsgPrefix = logger.PrefixIndentMsg + logger.MsgPrefix
	// logger.StartMsgPrefix += " . "
	logger.StartMsgPrefix += logger.IndentMsg
	logger.EndMsgPrefix += logger.IndentMsg
}

func (logger *Log) Startln(msg ...interface{}) {
	Msg := ""
	Name := ""
	for i, msg := range msg {
		if i > 0 {
			Msg += fmt.Sprintf("%v ", msg)
		} else {
			Name = fmt.Sprintf("%v", msg)
		}
	}
	logger.Start(Name, Msg)
}

func (logger *Log) Startf(name, format string, msg ...interface{}) {
	Name := name
	Msg := fmt.Sprintf(format, msg...)
	logger.Start(Name, Msg)
}

func (logger *Log) Printf(format string, msg ...interface{}) {
	logger.Lock.RLock()
	logger.MyPrintf("\n%s", logger.MsgPrefix)
	logger.Lock.RUnlock()
	logger.MyPrintf(format, msg...)
}

func (logger *Log) Println(msg ...interface{}) {
	logger.Lock.RLock()
	Msg := logger.MsgPrefix
	logger.Lock.RUnlock()

	for _, m := range msg {
		Msg += fmt.Sprintf("%v ", m)
	}
	logger.MyPrintf("\n%s", Msg)
}

// args: 函数名， 信息
func (logger *Log) End(msg string) (err error) {
	logger.Lock.Lock()
	defer logger.Lock.Unlock()
	// println("*****debug,", logger.FuncName, logger.Depth, logger.DepthInfo)
	err = fmt.Errorf("%s", msg)
	if logger.Depth > 0 {
		logger.Depth -= 1
	} else {
		return
	}

	// 更新前缀信息
	logger.MsgPrefix = logger.MsgPrefix[len(logger.PrefixIndentMsg):len(logger.MsgPrefix)]
	logger.StartMsgPrefix = logger.StartMsgPrefix[:len(logger.EndMsgPrefix)-len(logger.IndentMsg)]
	logger.EndMsgPrefix = logger.EndMsgPrefix[:len(logger.EndMsgPrefix)-len(logger.IndentMsg)]
	logger.MyPrintf("\n\n%s<- %v endfunc %s: %s\n\n", logger.EndMsgPrefix, logger.Depth, logger.FuncName, msg)
	// 移除最后一个元素
	logger.DepthInfo = logger.DepthInfo[:logger.Depth]
	if logger.Depth > 0 {
		logger.FuncName = logger.DepthInfo[logger.Depth-1].FuncName
	} else {
		logger.FuncName = ""
	}
	// println("**************debug,", logger.FuncName, logger.Depth, logger.DepthInfo)
	return
}

func (logger *Log) Endf(format string, msg ...interface{}) error {
	Msg := fmt.Sprintf(format, msg...)
	return logger.End(Msg)
}

func (logger *Log) Endln(msg ...interface{}) error {
	Msg := ""
	for _, m := range msg {
		Msg += fmt.Sprintf("%v ", m)
	}
	return logger.End(Msg)
}

/*  效果如下
> -> func sign: sign a xxxx
*  v = 5
*  b = 4
> .-> func hash:
*   v= 5
*   b = 4
> ..-> func hash2:
*    v= 4
< ..<- hash2
< .<- hash
< <- sign
*/
